package calculation

import (
	"cloudDevice2/sampleapi/protobuf"
	"cloudDevice2/sampleapi/utils"
	"encoding/json"
	"fmt"
	"log"
	"math"
	"strings"
	"time"

	"github.com/golang/protobuf/proto"
)

func PrepareSleepData(pbData []byte) {
	hisNotify := &protobuf.HisNotification{}
	err := proto.Unmarshal(pbData, hisNotify)
	if err != nil {
		log.Println(fmt.Sprintf("parse 80 healh history error:%s", err.Error()))
		return
	}

	switch hisNotify.GetData().(type) {
	case (*protobuf.HisNotification_HisData):
		hisData := hisNotify.GetHisData()
		switch hisNotify.GetType() {
		case protobuf.HisDataType(protobuf.HisDataType_HEALTH_DATA):
			health_data := hisData.GetHealth()
			unix_timestamp := health_data.GetTimeStamp().GetDateTime().GetSeconds()
			date_str := utils.ParsePbDateTime(int64(unix_timestamp))
			seq := hisData.GetSeq()
			sleep_dict := make(map[string]interface{})
			sleep_dict["Q"] = seq

			tm := time.Unix(int64(unix_timestamp), 0)
			t_arr := make([]int, 2)
			t_arr[0] = tm.Hour()
			t_arr[1] = tm.Minute()
			sleep_dict["T"] = t_arr

			pedo := health_data.GetPedoData()
			if pedo != nil {
				detail_dict := make(map[string]interface{})
				detail_dict["s"] = pedo.GetStep()
				detail_dict["c"] = pedo.GetCalorie()
				detail_dict["d"] = pedo.GetDistance()
				detail_dict["t"] = pedo.GetType()
				detail_dict["a"] = pedo.GetState() & 15
				sleep_dict["P"] = detail_dict
			}

			hr := health_data.GetHrData()
			if hr != nil {
				detail_dict := make(map[string]interface{})
				if hr.GetAvgBpm() > 0 {
					detail_dict["a"] = hr.GetAvgBpm()
				}
				if hr.GetMaxBpm() > 0 {
					detail_dict["x"] = hr.GetMaxBpm()
				}
				if hr.GetMinBpm() > 0 {
					detail_dict["n"] = hr.GetMinBpm()
				}
				sleep_dict["H"] = detail_dict
			}

			hrv := health_data.GetHrvData()
			if hrv != nil {
				detail_dict := make(map[string]interface{})
				if hrv.GetSDNN() > 0 {
					detail_dict["s"] = hrv.GetSDNN() / 10.0
				}
				if hrv.GetRMSSD() > 0 {
					detail_dict["r"] = hrv.GetRMSSD() / 10.0
				}
				if hrv.GetPNN50() > 0 {
					detail_dict["p"] = hrv.GetPNN50() / 10.0
				}
				if hrv.GetMEAN() > 0 {
					detail_dict["m"] = hrv.GetMEAN() / 10.0
				}
				fatigue := int(hrv.GetFatigue())
				if fatigue > -1000 {
					if fatigue <= 0 {
						fatigue = int(math.Log(float64(hrv.GetRMSSD())) * 20)
					}
					if fatigue > 0 {
						detail_dict["f"] = fatigue
					}
					exist := false
					for _ = range detail_dict {
						exist = true
						break
					}
					if exist {
						sleep_dict["V"] = detail_dict
					}
				}
			}

			sleep := health_data.GetSleepData()
			if sleep != nil {
				detail_dict := make(map[string]interface{})
				detail_dict["a"] = sleep.GetSleepData()
				if sleep.GetShutDown() {
					detail_dict["s"] = sleep.GetShutDown()
				}
				if sleep.GetCharge() {
					detail_dict["c"] = sleep.GetCharge()
				}
				sleep_dict["E"] = detail_dict
			}

			sleep_data_bytes, err := json.Marshal(sleep_dict)
			if err != nil {
				log.Println(err.Error())
				return
			}
			sleep_str := string(sleep_data_bytes)
			/*
				save sleep_str with date_str/seq, later to do sleep calculation,
				need combine all day's sleep_str
			*/
			log.Println(fmt.Sprintf("%s %d %s", date_str, seq, sleep_str))

			break
		}
	}
}

/*
Combine all day's sleep_str to one single string, in format json array.
sleepDataList should order by datetime
*/
func combineWholeDaySleepData(sleepDataList []string) string {
	if len(sleepDataList) == 0 {
		return "[]"
	}
	var sb strings.Builder
	sb.WriteString("[")
	for i := 0; i < len(sleepDataList); i++ {
		sleepData := sleepDataList[i]
		sb.WriteString(sleepData)
		if i == len(sleepDataList)-1 {
			sb.WriteString("]")
		} else {
			sb.WriteString(",")
		}
	}
	return sb.String()
}
